//  Copyright 2011 Charlie Garrett
//
//  Licensed under the Apache License, Version 2.0 (the "License");
//  you may not use this file except in compliance with the License.
//  You may obtain a copy of the License at
//
//  http://www.apache.org/licenses/LICENSE-2.0
//
//  Unless required by applicable law or agreed to in writing, software
//  distributed under the License is distributed on an "AS IS" BASIS,
//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//  See the License for the specific language governing permissions and
//  limitations under the License.
//
//  Register.h
//

#ifndef REGISTER_H
#define REGISTER_H

#include <string>

// When generating code for a clause  h :- b1, b2, ... bn
// The arguments of h and b* must get their conventional argument
// registers (An) as dictated by their positions.  Those values do not
// outlive the atom they occur in, so we never use an argument register
// of h in b1, for example.
// The permanent variables, those that occur in more than one of {h U b1}, b2, ... bn
// must get permanent registers (Yn) in the environment frame.  Those values are
// live from their point of definition to their last use.
// The remaining values can get temporary registers (Xn), which are clobbered by
// calls.  Since calls happen after b1, b2, ... bn, temporary value lifetimes are
// restricted to a block, where {h U b1} is considered one block.
// By convention, An and Xn are aliases for the same registers, but this does not
// seem to be essential and we could split them.

namespace logic {    
    using namespace std;
    
    struct Register {
        enum Kind {
            UNALLOCATED = 0,
            TEMPORARY = 1,
            PERMANENT = 2,
            ARGUMENT = 3
        };
        
        Kind kind;
        unsigned number;
        
        Register(Kind k = UNALLOCATED, unsigned n = 0) : kind(k), number(n) {}
        
        // Comparison operator for STL container classes.
        bool operator<(const Register &other) const;
        
        string ToString();
        
        static Register Unallocated;
    };
}  // namespace logic

#endif  // REGISTER_H
